<?php
declare (strict_types=1);

namespace app\admin\service\data\survey;

use app\admin\model\data\PaymentOrderItem;
use app\admin\model\data\SplitCourse;
use app\admin\model\data\Student;
use app\admin\model\data\StudentVip;
use app\admin\model\data\UserPaymentData;
use app\admin\model\data\VisitTotal;
use app\admin\service\data\DataService;
use app\common\helper\util\Timespan;

/**
 * 数据中心-数据概况
 */
class Survey extends DataService
{
    /**
     * 概况首页数据
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-15
     *
     * @return   [type]                         [description]
     */
    public function index()
    {
        $time = $this->parseTime();
        $data = [];
        // 销售额
        $data['sale_price'] = PaymentOrderItem::getSalePriceByTimespan($time);
        // 收益额
        $income_course  = SplitCourse::getIncomeByTimespan($time);
        $income_other   = PaymentOrderItem::getSalePriceByTimespanOfNonCourse($time);
        $data['income'] = $income_course + $income_other;
        // PV
        $data['pv'] = VisitTotal::getPvByTimespan($time);
        // uv
        $data['uv'] = VisitTotal::getUvByTimespan($time);
        // 付费用户数量
        $data['payment_user_count'] = PaymentOrderItem::getPaymentUserCountByTimespan($time);
        // 订单付费量
        $data['payment_order_count'] = PaymentOrderItem::getPaymentOrderCountByTimespan($time);

        // 如果获取的是今天的数据
        if ($this->timestr == 'today') {
            // 获取昨日数据
            $time                                  = Timespan::getYesterdayTimespan();
            $data['yesterday_sale_price']          = PaymentOrderItem::getSalePriceByTimespan($time);
            $yesterday_income_course               = SplitCourse::getIncomeByTimespan($time);
            $yesterday_income_other                = PaymentOrderItem::getSalePriceByTimespanOfNonCourse($time);
            $data['yesterday_income']              = $yesterday_income_course + $yesterday_income_other;
            $data['yesterday_pv']                  = VisitTotal::getPvByTimespan($time);
            $data['yesterday_uv']                  = VisitTotal::getUvByTimespan($time);
            $data['yesterday_payment_user_count']  = PaymentOrderItem::getPaymentUserCountByTimespan($time);
            $data['yesterday_payment_order_count'] = PaymentOrderItem::getPaymentOrderCountByTimespan($time);
        }

        return $this->parseToData($data, 1);
    }

    /**
     * 运营概括
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-15
     *
     * @return   [type]                         [description]
     */
    public function operate()
    {
        /** 销售额 */
        $sale_price = $this->getSalePriceData();
        /** 付费用户数 */
        $payment_user = $this->getPaymentUserData();

        $data = array_merge($sale_price, $payment_user);

        return $this->parseToData($data, 1);
    }

    /**
     * 今日销售额统计
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-16
     *
     * @return   [type]                         [description]
     */
    public function todaySalePrice()
    {
        $dateList = $this->parseDate('today');
        $rows     = [];
        foreach ($dateList as $date => $where) {
            $rows[] = [
                'date'       => $date,
                'sale_price' => PaymentOrderItem::getSalePriceByTimespan($where),
            ];
        }

        return $this->parseToData(['rows' => $rows], 1);
    }

    /**
     * 今日付费人数
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-16
     *
     * @return   [type]                         [description]
     */
    public function todayPaymentUserCount()
    {
        $dateList = $this->parseDate('today');
        $rows     = [];
        foreach ($dateList as $date => $where) {
            $rows[] = [
                'date'       => $date,
                'user_count' => PaymentOrderItem::getPaymentUserCountByTimespan($where),
            ];
        }

        return $this->parseToData(['rows' => $rows], 1);
    }

    /**
     * 今日流量
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-16
     *
     * @return   [type]                         [description]
     */
    public function todayFlow()
    {
        // pv
        $pv   = $this->getPvData();
        $uv   = $this->getUvData();
        $data = array_merge($pv, $uv);

        return $this->parseToData($data, 1);

    }

    /**
     * 今日下单
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-16
     *
     * @return   [type]                         [description]
     */
    public function todayPlaceOrder()
    {
        $data = [];
        // 今日下单人数
        $data['place_count'] = PaymentOrderItem::getPlaceOrderUserCountByTimespan(Timespan::getTodayTimespan());
        // 今日访客数 = UV
        $data['uv'] = VisitTotal::getUvByTimespan(Timespan::getTodayTimespan());
        // 转化率
        $data['user_conversion'] = $this->getProportionRate($data['uv'], $data['place_count'], 0);

        // 昨日下单人数
        $yesterday = PaymentOrderItem::getPlaceOrderUserCountByTimespan(Timespan::getYesterdayTimespan());
        // 昨日访客人数
        $uv = VisitTotal::getUvByTimespan(Timespan::getYesterdayTimespan());
        // 昨日转化率
        $yesterday_conversion = $this->getProportionRate($uv, $yesterday, 0);
        // 前日下单人数
        $before_yesterday = PaymentOrderItem::getPlaceOrderUserCountByTimespan(Timespan::getBeforeYesterdayTimespan());
        // 前日访客人数
        $uv = VisitTotal::getUvByTimespan(Timespan::getBeforeYesterdayTimespan());
        // 前日转化率
        $before_yesterday_conversion = $this->getProportionRate($uv, $before_yesterday, 0);
        // 日环比
        $data['user_conversion_ratio'] = $this->getRate($yesterday_conversion, $before_yesterday_conversion);

        // 上周昨日下单人数
        $lastweek_yesterday = PaymentOrderItem::getPlaceOrderUserCountByTimespan(Timespan::getLastWeekYesterdayTimespan());
        // 上周昨日访客人数
        $uv = VisitTotal::getUvByTimespan(Timespan::getLastWeekYesterdayTimespan());
        // 上周昨日转化率
        $lastweek_yesterday_conversion = $this->getProportionRate($uv, $lastweek_yesterday, 0);
        // 上上周昨日下单人数
        $last2week_yesterday = PaymentOrderItem::getPlaceOrderUserCountByTimespan(Timespan::getBeforeLastWeekYesterdayTimespan());
        // 上上周昨日访客人数
        $uv = VisitTotal::getUvByTimespan(Timespan::getBeforeLastWeekYesterdayTimespan());
        // 上上周昨日转化率
        $last2week_yesterday_conversion = $this->getProportionRate($uv, $last2week_yesterday, 0);
        // 周同比
        $data['user_conversion_week_ratio'] = $this->getRate($lastweek_yesterday_conversion, $last2week_yesterday_conversion);

        return $this->parseToData($data, 1);
    }

    /**
     * 今日支付情况
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-16
     *
     * @return   [type]                         [description]
     */
    public function todayPaymentOrder()
    {
        $data = [];
        // 今日下单量
        $data['place_count'] = PaymentOrderItem::getPlaceOrderCountByTimespan(Timespan::getTodayTimespan());
        // 今日下单支付量
        $data['payment_count'] = PaymentOrderItem::getPlaceOrderPaymentCountByTimespan(Timespan::getTodayTimespan());

        // 转化率
        $data['payment_conversion'] = $this->getProportionRate($data['place_count'], $data['payment_count'], 0);
        // 昨日下单量
        $yesterday = PaymentOrderItem::getPlaceOrderCountByTimespan(Timespan::getYesterdayTimespan());
        // 昨日下单支付量
        $payment = PaymentOrderItem::getPlaceOrderPaymentCountByTimespan(Timespan::getYesterdayTimespan());
        // 昨日转化率
        $yesterday_conversion = $this->getProportionRate($payment, $yesterday, 0);
        // 前日下单量
        $before_yesterday = PaymentOrderItem::getPlaceOrderCountByTimespan(Timespan::getBeforeYesterdayTimespan());
        // 前日下单支付量
        $payment = PaymentOrderItem::getPlaceOrderPaymentCountByTimespan(Timespan::getBeforeYesterdayTimespan());
        // 前日转化率
        $before_yesterday_conversion = $this->getProportionRate($payment, $before_yesterday, 0);
        // 日环比
        $data['payment_conversion_ratio'] = $this->getRate($yesterday_conversion, $before_yesterday_conversion);

        // 上周昨日下单量
        $lastweek_yesterday = PaymentOrderItem::getPlaceOrderCountByTimespan(Timespan::getLastWeekYesterdayTimespan());
        // 上周昨日下单支付量
        $payment = PaymentOrderItem::getPlaceOrderPaymentCountByTimespan(Timespan::getLastWeekYesterdayTimespan());
        // 上周昨日转化率
        $lastweek_yesterday_conversion = $payment ? ($lastweek_yesterday / $payment * 100) : 0;
        // 上上周昨日下单量
        $last2week_yesterday = PaymentOrderItem::getPlaceOrderCountByTimespan(Timespan::getBeforeLastWeekYesterdayTimespan());
        // 上上周昨日下单支付量
        $payment = PaymentOrderItem::getPlaceOrderPaymentCountByTimespan(Timespan::getBeforeLastWeekYesterdayTimespan());
        // 上上周昨日转化率
        $last2week_yesterday_conversion = $payment ? ($last2week_yesterday / $payment * 100) : 0;
        // 周同比
        $data['payment_conversion_week_ratio'] = $this->getRate($lastweek_yesterday_conversion, $last2week_yesterday_conversion);

        return $this->parseToData($data, 1);
    }

    /**
     * 今日用户
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-17
     *
     * @return   [type]                         [description]
     */
    public function todayUser()
    {
        $today     = Timespan::getTodayTimespan();
        $late7days = Timespan::getLateDaysTimespan(7);
        $data      = [];
        // 总注册人数
        $data['register_count_total'] = Student::count();
        // 今日注册人数
        $data['register_count_today'] = Student::whereDay('create_time', 'today')->count();
        // 最近7天登录人数
        $data['login_count_late_week'] = Student::whereBetween('last_login_time', $late7days)->count();
        // 付费总人数
        $data['payment_user_count_total'] = PaymentOrderItem::getPaymentUserCountByTimespan([0, time()]);
        // 今日新增付费人数
        $new                              = UserPaymentData::scope('mhm', 'user.mhm_id')->withJoin(['user' => ['mhm_id']])->whereDay('__TABLE__.create_time', 'today')->count();
        $data['payment_user_count_today'] = $new;
        // 付费用户活跃人数= 最近7天付费的用户登录过
        $data['payment_user_count_lateweek'] = PaymentOrderItem::scope('mhm', 'user.mhm_id')->withJoin(['user' => ['id'], 'pdorder' => ['status', 'payment_time']])->whereBetween('user.last_login_time', $late7days)->whereBetween('pdorder.payment_time', $late7days)->value('count(DISTINCT user.id)');
        // 老用户付款金额 = 这段时间付费的总金额 -  新用户付费金额
        // 付费总金额
        $totalPament = PaymentOrderItem::getSalePriceByTimespan($today);
        // 新用户付款总金额
        $newPayment = UserPaymentData::scope('mhm', 'user.mhm_id')->withJoin(['user' => ['mhm_id']])->whereDay('__TABLE__.create_time', 'today')->sum('payment');
        // 新老用户付款金额
        $data['student_payment_price'] = [
            [
                'title' => '老用户付款金额',
                'value' => $totalPament - $newPayment,
            ],
            [
                'title' => '新用户付款金额',
                'value' => $newPayment,
            ],
        ];
        // 老用户付费人数 = 这段时间付费的总人数 - 新用户人数
        // 付费总人数
        $totalCount = PaymentOrderItem::getPaymentUserCountByTimespan($today);
        // 新老用户付款人数
        $data['student_payment_user'] = [
            [
                'title' => '老用户付款人数',
                'value' => $totalCount - $new,
            ],
            [
                'title' => '新用户付款人数',
                'value' => $new,
            ],
        ];
        // 新增会员数
        $data['vip_today'] = StudentVip::scope('mhm', 'user.mhm_id')->withJoin(['user' => ['mhm_id']])->whereDay('__TABLE__.create_time', 'today')->count();
        // 累计会员数
        $data['vip_total'] = StudentVip::scope('mhm', 'user.mhm_id')->withJoin(['user' => ['mhm_id']])->count();
        return $this->parseToData($data, 1);
    }

    /**
     * 用户注册量 = 用户数
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-16
     *
     * @param array $timespan [description]
     * @return   [type]                                   [description]
     */
    protected function getRegisterCountByTimespan(array $timespan)
    {
        return Student::getRegisterCountByTime($timespan[1]);
    }

    /**
     * 销售额统计数据
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-16
     *
     * @return   [type]                         [description]
     */
    protected function getSalePriceData()
    {
        $data = [];
        // 当前需要统计的时间
        $time = $this->parseTime();
        // 当前销售额
        $data['sale_price'] = PaymentOrderItem::getSalePriceByTimespan($time);
        // 昨日销售额
        $yesterday = PaymentOrderItem::getSalePriceByTimespan(Timespan::getYesterdayTimespan());
        // 前日销售额
        $before_yesterday = PaymentOrderItem::getSalePriceByTimespan(Timespan::getBeforeYesterdayTimespan());
        // 销售额日环比
        $data['sale_price_ratio'] = $this->getRate($yesterday, $before_yesterday);
        // 上周昨日销售额
        $lastweek_yesterday = PaymentOrderItem::getSalePriceByTimespan(Timespan::getLastWeekYesterdayTimespan());
        // 上上周昨日销售额
        $last2week_yesterday = PaymentOrderItem::getSalePriceByTimespan(Timespan::getBeforeLastWeekYesterdayTimespan());
        // 销售额周同比
        $data['sale_price_week_ratio'] = $this->getRate($lastweek_yesterday, $last2week_yesterday);

        return $data;
    }

    /**
     * 获取付费用户统计数据
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-16
     *
     * @return   [type]                         [description]
     */
    protected function getPaymentUserData()
    {
        $data = [];
        // 当前需要统计的时间
        $time = $this->parseTime();
        // 当前付费用户数
        $data['payment_user_count'] = PaymentOrderItem::getPaymentUserCountByTimespan($time);
        // 昨日付费用户数
        $yesterday = PaymentOrderItem::getPaymentUserCountByTimespan(Timespan::getYesterdayTimespan());
        // 前日付费用户数
        $before_yesterday = PaymentOrderItem::getPaymentUserCountByTimespan(Timespan::getBeforeYesterdayTimespan());
        // 付费用户数日环比
        $data['payment_user_count_ratio'] = $this->getRate($yesterday, $before_yesterday);
        // 上周昨日付费用户数
        $lastweek_yesterday = PaymentOrderItem::getPaymentUserCountByTimespan(Timespan::getLastWeekYesterdayTimespan());
        // 上上周昨日付费用户数
        $last2week_yesterday = PaymentOrderItem::getPaymentUserCountByTimespan(Timespan::getBeforeLastWeekYesterdayTimespan());
        // 付费用户数周同比
        $data['payment_user_count_week_ratio'] = $this->getRate($lastweek_yesterday, $last2week_yesterday);
        // 当前用户总数
        $total_user_count = $this->getRegisterCountByTimespan($time);

        // 付费用户占比
        $data['payment_user_count_rate'] = $this->getProportionRate($total_user_count, $data['payment_user_count'], 0);

        // 昨日用户数量
        $yesterday_user_count = $this->getRegisterCountByTimespan(Timespan::getYesterdayTimespan());
        // 昨日用户付费占比
        $yesterday_rate = $this->getProportionRate($yesterday_user_count, $yesterday);

        // 前日用户注册量
        $before_yesterday_user_count = $this->getRegisterCountByTimespan(Timespan::getBeforeYesterdayTimespan());
        // 前日用户付费占比
        $before_yesterday_rate = $this->getProportionRate($before_yesterday_user_count, $before_yesterday);

        // 付费用户占比的日环比
        $data['payment_user_count_rate_ratio'] = $this->getRate($yesterday_rate, $before_yesterday_rate);
        // 上周昨日注册数
        $lastweek_yesterday_user_count = $this->getRegisterCountByTimespan(Timespan::getLastWeekYesterdayTimespan());
        // 上周昨日付费用户占比
        $lastweek_yesterday_rate = $this->getProportionRate($lastweek_yesterday_user_count, $lastweek_yesterday);
        // 上上周昨日注册数
        $last2week_yesterday_user_count = $this->getRegisterCountByTimespan(Timespan::getBeforeLastWeekYesterdayTimespan());
        // 上上周昨日付费用户占比
        $last2week_yesterday_rate = $this->getProportionRate($last2week_yesterday_user_count, $last2week_yesterday);
        // 上上周昨日的付费占比周同比
        $data['payment_user_count_rate_week_ratio'] = $this->getRate($yesterday_rate, $before_yesterday_rate);

        return $data;
    }

    /**
     * 获取PV统计数据
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-16
     *
     * @return   [type]                         [description]
     */
    public function getPvData()
    {
        $data = [];
        // 今日pv
        $data['pv'] = VisitTotal::getPvByTimespan(Timespan::getTodayTimespan());
        // 昨日pv
        $yesterday = VisitTotal::getPvByTimespan(Timespan::getYesterdayTimespan());
        // 前日pv
        $before_yesterday = VisitTotal::getPvByTimespan(Timespan::getBeforeYesterdayTimespan());
        // pv日环比
        $data['pv_ratio'] = $this->getRate($yesterday, $before_yesterday);
        // 上周昨日pv
        $lastweek_yesterday = VisitTotal::getPvByTimespan(Timespan::getLastWeekYesterdayTimespan());
        // 上上周昨日pv
        $last2week_yesterday = VisitTotal::getPvByTimespan(Timespan::getBeforeLastWeekYesterdayTimespan());
        // pv 周同比
        $data['pv_week_ratio'] = $this->getRate($lastweek_yesterday, $last2week_yesterday);

        return $data;
    }

    /**
     * 获取UV统计数据
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-16
     *
     * @return   [type]                         [description]
     */
    public function getUvData()
    {
        $data = [];
        // 今日uv
        $data['uv'] = VisitTotal::getUvByTimespan(Timespan::getTodayTimespan());
        // 昨日pv
        $yesterday = VisitTotal::getUvByTimespan(Timespan::getYesterdayTimespan());
        // 前日uv
        $before_yesterday = VisitTotal::getUvByTimespan(Timespan::getBeforeYesterdayTimespan());
        // uv日环比
        $data['uv_ratio'] = $this->getRate($yesterday, $before_yesterday);
        // 上周昨日uv
        $lastweek_yesterday = VisitTotal::getUvByTimespan(Timespan::getLastWeekYesterdayTimespan());
        // 上上周昨日uv
        $last2week_yesterday = VisitTotal::getUvByTimespan(Timespan::getBeforeLastWeekYesterdayTimespan());
        // uv 周同比
        $data['uv_week_ratio'] = $this->getRate($lastweek_yesterday, $last2week_yesterday);

        return $data;
    }

    /**
     * 计算环比,同比
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-07-15
     *
     * @param    [type]                         $base        [description]
     * @param    [type]                         $divisor [description]
     * @return   [type]                                           [description]
     */
    protected function getRate($base, $divisor)
    {
        if ($base > 0 && $divisor == 0) {
            $rate = 100;
        } else if ($divisor == 0) {
            $rate = 0;
        } else {
            $rate = round((($base - $divisor) / $divisor) * 100, 2);
        }

        return $rate > 100 ? 100 : $rate;

    }

}
